{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "cc0d17f8",
   "metadata": {},
   "source": [
    "# PandasDataFrameOutputParser\n",
    "\n",
    "**Pandas DataFrame**은 Python 프로그래밍 언어에서 널리 사용되는 데이터 구조로, 데이터 조작 및 분석을 위한 강력한 도구입니다. DataFrame은 구조화된 데이터를 효과적으로 다루기 위한 포괄적인 도구 세트를 제공하며, 이를 통해 데이터 정제, 변환 및 분석과 같은 다양한 작업을 수행할 수 있습니다.\n",
    "\n",
    "이 **출력 파서**는 사용자가 임의의 Pandas DataFrame을 지정하여 해당 DataFrame에서 데이터를 추출하고, 이를 형식화된 사전(dictionary) 형태로 조회할 수 있게 해주는 LLM(Large Language Model) 기반 도구입니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "de387034",
   "metadata": {},
   "outputs": [],
   "source": [
    "from dotenv import load_dotenv\n",
    "\n",
    "load_dotenv()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fe9492a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# LangSmith 추적을 설정합니다. https://smith.langchain.com\n",
    "# !pip install langchain-teddynote\n",
    "from langchain_teddynote import logging\n",
    "\n",
    "# 프로젝트 이름을 입력합니다.\n",
    "logging.langsmith(\"CH03-OutputParser\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6c6d4c70",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pprint\n",
    "from typing import Any, Dict\n",
    "\n",
    "import pandas as pd\n",
    "from langchain.output_parsers import PandasDataFrameOutputParser\n",
    "from langchain_core.prompts import PromptTemplate\n",
    "from langchain_openai import ChatOpenAI"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a500317",
   "metadata": {},
   "outputs": [],
   "source": [
    "# ChatOpenAI 모델 초기화 (gpt-3.5-turbo 모델 사용을 권장합니다)\n",
    "model = ChatOpenAI(temperature=0, model_name=\"gpt-3.5-turbo\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38a9f23d",
   "metadata": {},
   "source": [
    "`format_parser_output` 함수는 파서 출력을 사전 형식으로 변환하고 출력 형식을 지정하는 데 사용됩니다. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3dadcb4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 출력 목적으로만 사용됩니다.\n",
    "def format_parser_output(parser_output: Dict[str, Any]) -> None:\n",
    "    # 파서 출력의 키들을 순회합니다.\n",
    "    for key in parser_output.keys():\n",
    "        # 각 키의 값을 딕셔너리로 변환합니다.\n",
    "        parser_output[key] = parser_output[key].to_dict()\n",
    "    # 예쁘게 출력합니다.\n",
    "    return pprint.PrettyPrinter(width=4, compact=True).pprint(parser_output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2dca1ed",
   "metadata": {},
   "source": [
    "- `titanic.csv` 데이터를 읽어온 뒤 DataFrame 을 로드하여 `df` 변수에 할당합니다.\n",
    "- PandasDataFrameOutputParser를 사용하여 DataFrame을 파싱합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f4228af1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 원하는 Pandas DataFrame을 정의합니다.\n",
    "df = pd.read_csv(\"./data/titanic.csv\")\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "436f7dea",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 파서를 설정하고 프롬프트 템플릿에 지시사항을 주입합니다.\n",
    "parser = PandasDataFrameOutputParser(dataframe=df)\n",
    "\n",
    "# 파서의 지시사항을 출력합니다.\n",
    "print(parser.get_format_instructions())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd2699de",
   "metadata": {},
   "source": [
    "컬럼에 대한 값을 조회하는 예제입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "42688b23",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 열 작업 예시입니다.\n",
    "df_query = \"Age column 을 조회해 주세요.\"\n",
    "\n",
    "\n",
    "# 프롬프트 템플릿을 설정합니다.\n",
    "prompt = PromptTemplate(\n",
    "    template=\"Answer the user query.\\n{format_instructions}\\n{question}\\n\",\n",
    "    input_variables=[\"question\"],  # 입력 변수 설정\n",
    "    partial_variables={\n",
    "        \"format_instructions\": parser.get_format_instructions()\n",
    "    },  # 부분 변수 설정\n",
    ")\n",
    "\n",
    "# 체인 생성\n",
    "chain = prompt | model | parser\n",
    "\n",
    "# 체인 실행\n",
    "parser_output = chain.invoke({\"question\": df_query})\n",
    "\n",
    "# 출력\n",
    "format_parser_output(parser_output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4dd6636",
   "metadata": {},
   "source": [
    "첫 번째 행을 검색하는 예시입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "867ced38",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 행 조회 예시입니다.\n",
    "df_query = \"Retrieve the first row.\"\n",
    "\n",
    "# 체인 실행\n",
    "parser_output = chain.invoke({\"question\": df_query})\n",
    "\n",
    "# 결과 출력\n",
    "format_parser_output(parser_output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a936bdcd",
   "metadata": {},
   "source": [
    "특정 열에서 일부 행의 평균을 검색하는 작업 예제입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e479306f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# row 0 ~ 4의 평균 나이를 구합니다.\n",
    "df[\"Age\"].head().mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a26883b4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 임의의 Pandas DataFrame 작업 예시, 행의 수를 제한합니다.\n",
    "df_query = \"Retrieve the average of the Ages from row 0 to 4.\"\n",
    "\n",
    "# 체인 실행\n",
    "parser_output = chain.invoke({\"question\": df_query})\n",
    "\n",
    "# 결과 출력\n",
    "print(parser_output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "62e97f39",
   "metadata": {},
   "source": [
    "다음은 요금(Fare) 에 대한 평균 가격을 산정하는 예시입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "743b51ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "68a97d89",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 잘못 형식화된 쿼리의 예시입니다.\n",
    "df_query = \"Calculate average `Fare` rate.\"\n",
    "\n",
    "# 체인 실행\n",
    "parser_output = chain.invoke({\"question\": df_query})\n",
    "\n",
    "# 결과 출력\n",
    "print(parser_output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d7dd2f2b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 결과 검증\n",
    "df[\"Fare\"].mean()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py-test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
